/*  SOURCE FILE: MOVEFILE.C  */
/**************************************************************************/
/*  MOVEFILE - File Move Utility  PUBLIC DOMAIN                           */
/*  Original Author: James W. Drash, CompuServe ID [76607,70]             */
/*                                                                        */
/*  This program moves files from one directory to another                */
/*     External Routines Used:                                            */
/*       exparg   - used to expand the source file args (wildcards)       */
/*                                                                        */
/*  Developed: Using Borland Turbo C verion 1.00                          */
/*  Compile Options: Model - Tiny; Code Generation - No Floating Point    */
/**************************************************************************/
#include <stdio.h>
#include <dir.h>
#include <dos.h>
#include <io.h>
#include <fcntl.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#include <process.h>
#include <exparg.h>
#include <exparg.c>

void getpname(char *,char *);
void help(char *);
int movem(char *,char *,char *);
int c_break(void);
int newfile(char *,char *,char *);
int targ_there(char *,char *);
int copyem(char *,char *,char *);
int same_drive(char *,char *);

static char version[] = {"File Move Utility, Version 1.20, " \
                           "PUBLIC DOMAIN"};
void main(int argc,char **argv)
{
  static char pgm[MAXFILE] = { "movefile" };
  char target[MAXPATH];
  int i, j;
  /* get program name from DOS (version 3.00 and later) */
  if (_osmajor >= 3)
		  getpname(*argv,pgm);
        ctrlbrk(c_break);
        /* print opening banner for program */
		printf("%s - %s\n\n",pgm,version);
  /* if we don't have DOS 2.00 or higher then exit  */
  if (_osmajor < 2) {
          printf("%s: Requires PC/MS DOS 2.00 or higher\n",\
                 "DOS version %d.%d installed\n",pgm,_osmajor,_osminor);
		  exit(1); }
  /* check for right number of arguments, give help if not */
  if (argc < 3 || strcmp(argv[1],"?") == 0) {
    help(pgm);
	exit(1); }
		/* uppercase everything */
        for (i = 1; i < argc; i ++)
          for (j = 0; j < strlen(argv[i]); j++)
			argv[i][j] = toupper(argv[i][j]);
        /* get target */
        strcpy(target,argv[argc - 1]);
		--argc;
  /* if target doesn't look like a directory make it */
  if (target[strlen(target) - 1] != '\\')
	strcat(target,"\\");
  /* check to see that the target exists */
  if (targ_there(target,pgm) != 0) { exit(1);}
        /* expand args */
		argv = exparg(&argc,argv);
        /* for each file move it */
        for (i = 1; i < argc; i++) {
          /* if same drive then rename should work */
          if (same_drive(argv[i],target) == 0) {
            if (movem(argv[i],target,pgm) == 0)
              printf("%s moved to %s\n",argv[i],target);
            else
              printf("%s: Unable to move - %s\n",pgm,argv[i]);
			}
          /* else copy and delete should work */
          else {
            /* if the copy worked try to delete the source */
            if (copyem(argv[i],target,pgm) != 0)
              printf("%s: Unable to move - %s\n",pgm,argv[i]);
            else {
              printf("%s moved to %s\n",argv[i],target);
              /* if the delete falied tell the user */
			   if (unlink(argv[i]) != 0)
				printf("%s",_strerror(pgm));}}}
  exit(0);}
int c_break(void)
{ printf("Ctrl-Break hit. Program aborting ...\n");
  fcloseall();
  exit(1);
  return;}
void help(char *name)
{ printf("Usage: %s source ... target\n"  \
         "where source - file(s) to be moved (wildcards allowed)\n" \
         "      target - destination directory\n\n" \
         "multiple source specications allowed\n" \
         "example - %s fu.bar file.* test*.bas \\basic\n\n",name,name);
}
void getpname(char *source,char *pgm)
{ char drive[MAXDRIVE];
  char dir[MAXDIR];
  char ext[MAXEXT];
  int i;
  /* take apart the source */
  fnsplit(source,drive,dir,pgm,ext);
        /* lowercase everything */
        for(i = 0; i < strlen(pgm); i++)
          pgm[i] = tolower(pgm[i]);
}
int targ_there(char *target,char *pgm)
{ struct ffblk ffblk;
  char drive[MAXDRIVE];
  char dir[MAXDIR];
  char file[MAXFILE];
  char ext[MAXEXT];
  char targchk[MAXPATH];
  int i;
  /* take apart the source */
  fnsplit(target,drive,dir,file,ext);
  /* if we're trying to move to the root its ok */
  if (strcmp(dir,"\\") == 0)
	return 0;
  /* copy the target to the check string and strip off the
     trailing "\" */
  strcpy(targchk,target);
  targchk[strlen(targchk) -1] = '\0';
  /* try to find the target */
  if (findfirst(targchk,&ffblk,FA_DIREC) == 0) return 0;
  else {  printf("%s",_strerror(pgm));
          printf("target: %s\n",target);
		  return -1;}
}
int same_drive(char *source,char *target)
{ char sdrive[MAXDRIVE];
  char sdir[MAXDIR];
  char sfile[MAXFILE];
  char sext[MAXEXT];
  char tdrive[MAXDRIVE];
  char tdir[MAXDIR];
  char tfile[MAXFILE];
  char text[MAXEXT];
  char curdrive[MAXDRIVE];
  int retcode;
  /* get current drive */
  curdrive[0] = 'A' + getdisk();
  curdrive[1] = ':';
  curdrive[2] = '\0';
  /* take apart the source and target */
  fnsplit(source,sdrive,sdir,sfile,sext);
  fnsplit(target,tdrive,tdir,tfile,text);
  /* if either drive is missing put it in */
  if (strlen(sdrive) == 0) strcpy(sdrive,curdrive);
  if (strlen(tdrive) == 0) strcpy(tdrive,curdrive);
  /* see if the drives are the same */
  if (strcmp(sdrive,tdrive) == 0) retcode = 0;
  else retcode = -1;
  /* put together the source and target */
  fnmerge(source,sdrive,sdir,sfile,sext);
  fnmerge(target,tdrive,tdir,tfile,text);
  return retcode;
}
int newfile(char *source,char *target,char *targ_fn)
{ char sdrive[MAXDRIVE];
  char sdir[MAXDIR];
  char sfile[MAXFILE];
  char sext[MAXEXT];
  char tdrive[MAXDRIVE];
  char tdir[MAXDIR];
  char tfile[MAXFILE];
  char text[MAXEXT];
  char curdrive[MAXDRIVE];
  int flag;
  /* take apart the source */
  flag = fnsplit(source,sdrive,sdir,sfile,sext);
        /* by this time in the program the program their should be no
           wildcards */
        if (flag & WILDCARDS) {
          targ_fn = '\0';
		  return -1;}
        else {
          /* take apart the target */
          fnsplit(target,tdrive,tdir,tfile,text);
          /* put together the new target filename */
          fnmerge(targ_fn,tdrive,tdir,sfile,sext);
		  return 0;}
}
int movem(char *source,char *target,char *pgm)
{ char targ_fn[MAXPATH];
  /* if if we are not able to create a new_file name, bail out */
		if (newfile(source,target,targ_fn) != 0) return -1;
        if (rename(source, targ_fn) != 0) {
          unlink(targ_fn);
          if (rename(source, targ_fn) != 0) {
            printf("%s",_strerror(pgm));
			return -1;}
		  else return 0;
          }
		else return 0;
}
int copyem(char *source,char *target,char *pgm)
{ int bytes;
  FILE *input, *output;
  char iobuf[BUFSIZ];
  struct ftime instamp;
  struct ftime outstamp;
  char targ_fn[MAXPATH];
  char *outbuf;
  int temp_hand;
  /* if if we are not able to create a new_file name, bail out */
		if (newfile(source,target,targ_fn) != 0) return -1;
		if ((input = fopen(source,"rb+")) == NULL) {
           printf("%s: Unable to open: %s\n",pgm,source);
		   fcloseall();  return -1;}
		if ((output = fopen(targ_fn,"wb+")) == NULL) {
           unlink(targ_fn);
		   if ((output = fopen(targ_fn,"wb+")) == NULL) {
             printf("%s: Unable to open: %s\n",pgm,targ_fn);
             fcloseall();
			 return -1;}
		 }
		   do {bytes = fread(iobuf,sizeof(char),BUFSIZ,input);
             if (ferror(input)) {
               printf("%s",_strerror(pgm));
               printf("unable to move: %s\n",source);
               fclose(input);
               fclose(output);
			   return -1;}
             fwrite(iobuf,sizeof(char),bytes,output);
             if (ferror(output)) {
               printf("%s",_strerror(pgm));
               printf("unable to move: %s\n",source);
               fclose(input);
               fclose(output);
			   return -1;}
             } while(!feof(input));
           getftime(fileno(input),&instamp);
           outstamp = instamp;
           fclose(input);
           fclose(output);
           if ((temp_hand = open(targ_fn,O_RDWR|O_BINARY)) > 0) {
             setftime(temp_hand,&outstamp);
			 close(temp_hand);}
		   else printf("%s",_strerror(pgm));
		   return 0;
}